# -*- coding: utf-8 -*-

from git import GitCommandError
from git.repo import Repo

from conf.entity.module.git_config import GitProject


class GitOperation:
    repo: Repo
    project: GitProject

    def __init__(self, repo: Repo, project: GitProject):
        self.repo = repo
        self.project = project

    def stash_if_possible(self):
        current_status = self.repo.git.status()
        if 'Changes to be committed' in current_status:
            print('stash uncommitted codes')
            self.repo.git.stash()
            self.project.need_stash = True

    def pop_stash_if_possible(self):
        if self.project.need_stash:
            self.repo.git.stash('pop')

    def fetch_from_remote(self):
        self.repo.git.fetch()

    def pull_from_remote(self, target_branch: str):
        self.repo.git.checkout(target_branch)
        self.repo.git.pull('origin', target_branch)
        last_commit = self.repo.git.log('-1')

        # 获取最近一次提交commit id
        return last_commit.split('\n')[0].split(' ')[1]

    def is_diff_branches(self, base_branch: str, compare_branch: str) -> bool:
        res = self.repo.git.diff(base_branch, compare_branch)
        return res != ''

    def delete_local_branch(self, target_branch: str):
        branch_str = self.repo.git.branch()
        branches = branch_str.split('\n')
        for branch_item in branches:
            # 当前所在分支，去掉 '*'；其他情况，去除空格
            branch_item = branch_item.replace('*', '').strip()
            if branch_item != target_branch:
                # 切换到第一个非target_branch的分支
                self.repo.git.checkout(branch_item)
                try:
                    self.repo.git.branch('-D', target_branch)
                except GitCommandError as e:
                    print(f'error when execute: {e.command}, target branch not exist')
                break

    def merge_branch(self, project, base_branch: str, branch_to_be_merged: str) -> bool:
        try:
            merge_result = self.repo.git.merge(branch_to_be_merged)
        except GitCommandError as e:
            print(f'conflict occurs when execute: {e.command}, abort')
            self.repo.git.merge('--abort')
            project.has_conflict = True
            return False
        else:
            if 'Already up to date' in merge_result:
                return False
            print('do_merge successfully')
            self.repo.git.push('origin', base_branch)
            return True

    def create_tag(self, project: GitProject, base_branch: str, tag_name: str, tag_comment: str) -> bool:
        # 从远程仓库拉取
        self.repo.git.fetch()

        # 检查是否存在tag_name
        tag_str = self.repo.git.tag('-l', tag_name)
        if tag_str != '':
            print(f'tag {tag_name} already exists!')
            return False

        try:
            self.pull_from_remote(base_branch)
            if tag_comment is not None or tag_comment == '':
                self.repo.git.tag('-a', tag_name, '-m', tag_comment)
            else:
                self.repo.tag('-a',  tag_name)
            # 创建tag后，推送到远程仓库
            self.repo.git.push('origin', tag_name)
            project.tag_operated = True
            return True
        except GitCommandError as e:
            print(f'error when execute: {e.command}, reason: {e.stdout}')
            return False

    def delete_tag(self, project: GitProject, tag_name: str):
        # 从远程仓库拉取
        self.repo.git.fetch()
        # 检查是否存在tag_name
        tag_str = self.repo.git.tag('-l', tag_name)
        if tag_str == '':
            print(f'tag {tag_name} not exist!')
            return False

        try:
            self.repo.git.tag('-d', tag_name)
            # 删除tag后，推送到远程仓库
            self.repo.git.push('origin', '--delete', tag_name)
            project.tag_operated = True
            return True
        except GitCommandError as e:
            print(f'error when execute: {e.command}, reason: {e.status}')
            return False

